import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { SelectCourse } from './entities/select_course.entity';
import { CreateSelectCourseDto } from './dto/create-select-course.dto';
import { UpdateScoreDto } from './dto/update-score.dto';
import { QuerySelectCourseDto } from './dto/query-select-course.dto';
import { CourseOffering } from '../course_offering/entities/course_offering.entity';
import { Student } from '../student/entities/student.entity';
import { Semester } from '../semester/entities/semester.entity';

@Injectable()
export class SelectCourseService {
    constructor(
        @InjectRepository(SelectCourse)
        private readonly selectRepo: Repository<SelectCourse>,
        @InjectRepository(CourseOffering)
        private readonly offeringRepo: Repository<CourseOffering>,
        @InjectRepository(Student)
        private readonly studentRepo: Repository<Student>,
        @InjectRepository(Semester)
        private readonly semesterRepo: Repository<Semester>
    ) {}

    // 学生选课
    async create(createDto: CreateSelectCourseDto) {
        // 检查学生和课程是否存在
        const [student, offering] = await Promise.all([
            this.studentRepo.findOneBy({ sno: createDto.sno }),
            this.offeringRepo.findOne({
                where: { offering_id: createDto.offering_id },
                relations: ['semester']
            })
        ]);

        if (!student || !offering) {
            throw new NotFoundException('学生或课程不存在');
        }

        // 检查是否是当前学期
        const currentSemester = await this.semesterRepo.findOne({
            where: { status: 'current' }
        });

        if (!currentSemester) {
            throw new BadRequestException('当前没有进行中的学期');
        }

        if (offering.semester.semester_id !== currentSemester.semester_id) {
            throw new BadRequestException('只能选择当前学期的课程');
        }

        // 检查课程容量
        if (offering.enrolled_count >= offering.capacity) {
            throw new BadRequestException('课程已满');
        }

        // 检查是否已选过该课程
        const existing = await this.selectRepo.findOne({
            where: {
                student: { sno: createDto.sno.toString() },
                courseOffering: { offering_id: createDto.offering_id },
                status: 'selected'
            }
        });

        if (existing) {
            throw new BadRequestException('已经选过该课程');
        }

        // 创建选课记录
        const selectCourse = this.selectRepo.create({
            student,
            courseOffering: offering
        });

        // 更新课程已选人数
        offering.enrolled_count += 1;
        await this.offeringRepo.save(offering);

        return this.selectRepo.save(selectCourse);
    }

    // 学生退课
    async dropCourse(select_id: number) {
        const selectCourse = await this.selectRepo.findOne({
            where: { select_id },
            relations: ['courseOffering', 'courseOffering.semester']
        });

        if (!selectCourse) {
            throw new NotFoundException('选课记录不存在');
        }

        if (selectCourse.status === 'dropped') {
            throw new BadRequestException('该课程已退选');
        }

        // 检查是否是当前学期
        const currentSemester = await this.semesterRepo.findOne({
            where: { status: 'current' }
        });

        if (!currentSemester || selectCourse.courseOffering.semester.semester_id !== currentSemester.semester_id) {
            throw new BadRequestException('只能退选当前学期的课程');
        }

        // 更新选课状态
        selectCourse.status = 'dropped';
        selectCourse.dropTime = new Date();

        // 更新课程已选人数
        const offering = selectCourse.courseOffering;
        offering.enrolled_count -= 1;
        await this.offeringRepo.save(offering);

        return this.selectRepo.save(selectCourse);
    }

    // 教师录入成绩
    async updateScore(select_id: number, updateScoreDto: UpdateScoreDto) {
        const selectCourse = await this.selectRepo.findOne({
            where: { select_id },
            relations: ['courseOffering', 'courseOffering.course']
        });

        if (!selectCourse) {
            throw new NotFoundException('选课记录不存在');
        }

        if (selectCourse.status === 'dropped') {
            throw new BadRequestException('该课程已退选，无法录入成绩');
        }

        selectCourse.score = updateScoreDto.score;
        return this.selectRepo.save(selectCourse);
    }

    // 查询选课记录
    async findAll(query: QuerySelectCourseDto) {
        const { page = 1, pageSize = 10, ...filters } = query;
        const skip = (page - 1) * pageSize;

        const queryBuilder = this.selectRepo.createQueryBuilder('select')
            .leftJoinAndSelect('select.student', 'student')
            .leftJoinAndSelect('select.courseOffering', 'offering')
            .leftJoinAndSelect('offering.course', 'course')
            .leftJoinAndSelect('offering.teacher', 'teacher')
            .leftJoinAndSelect('offering.semester', 'semester');

        // 添加过滤条件
        if (filters.semester_id) {
            queryBuilder.andWhere('offering.semester_id = :semester_id', { semester_id: filters.semester_id });
        }
        if (filters.sno) {
            queryBuilder.andWhere('select.sno = :sno', { sno: filters.sno });
        }
        if (filters.tno) {
            queryBuilder.andWhere('offering.tno = :tno', { tno: filters.tno });
        }
        if (filters.status) {
            queryBuilder.andWhere('select.status = :status', { status: filters.status });
        }

        const [list, itemCount] = await queryBuilder
            .skip(skip)
            .take(pageSize)
            .orderBy('select.select_id', 'DESC')
            .getManyAndCount();

        return {
            list,
            itemCount,
            page: page.toString(),
            pageSize: pageSize.toString(),
            pageCount: Math.ceil(itemCount / pageSize)
        };
    }

    // 获取学生选课列表
    async findByStudent(sno: string, semester_id?: number) {
        const queryBuilder = this.selectRepo.createQueryBuilder('select')
            .leftJoinAndSelect('select.courseOffering', 'offering')
            .leftJoinAndSelect('offering.course', 'course')
            .leftJoinAndSelect('offering.teacher', 'teacher')
            .leftJoinAndSelect('offering.semester', 'semester')
            .where('select.sno = :sno', { sno });

        if (semester_id) {
            queryBuilder.andWhere('offering.semester_id = :semester_id', { semester_id });
        }

        return queryBuilder.getMany();
    }

    // 获取教师课程学生列表（添加分页和课程号筛选）
    async findByTeacher(tno: number, semester_id?: number, cno?: number, page: number = 1, pageSize: number = 10) {
        const skip = (page - 1) * pageSize;
        
        const queryBuilder = this.selectRepo.createQueryBuilder('select')
            .leftJoinAndSelect('select.student', 'student')
            .leftJoinAndSelect('select.courseOffering', 'offering')
            .leftJoinAndSelect('offering.course', 'course')
            .leftJoinAndSelect('offering.teacher', 'teacher')
            .leftJoinAndSelect('offering.semester', 'semester')
            .where('offering.teacher.tno = :tno', { tno })
            .andWhere('select.status = :status', { status: 'selected' });

        if (semester_id) {
            queryBuilder.andWhere('offering.semester.semester_id = :semester_id', { semester_id });
        }

        // 添加课程号筛选条件
        if (cno) {
            queryBuilder.andWhere('offering.course.cno = :cno', { cno });
        }

        const [list, itemCount] = await queryBuilder
            .skip(skip)
            .take(pageSize)
            .orderBy('select.select_id', 'DESC')
            .getManyAndCount();

        return {
            list,
            itemCount,
            page: page.toString(),
            pageSize: pageSize.toString(),
            pageCount: Math.ceil(itemCount / pageSize)
        };
    }

    // 获取教师的所有开课（用于成绩管理）
    async getTeacherCourses(tno: number, semester_id?: number) {
        const queryBuilder = this.offeringRepo.createQueryBuilder('offering')
            .leftJoinAndSelect('offering.course', 'course')
            .leftJoinAndSelect('offering.semester', 'semester')
            .leftJoinAndSelect('offering.teacher', 'teacher')
            .where('offering.teacher.tno = :tno', { tno })
            .andWhere('offering.status = :status', { status: 'open' });

        if (semester_id) {
            queryBuilder.andWhere('offering.semester.semester_id = :semester_id', { semester_id });
        }

        const courses = await queryBuilder.getMany();
        
        // 为每个课程添加学生数量统计
        const result = await Promise.all(courses.map(async (course) => {
            const studentCount = await this.selectRepo.count({
                where: {
                    courseOffering: { offering_id: course.offering_id },
                    status: 'selected'
                }
            });
            
            return {
                ...course,
                studentCount
            };
        }));

        return result;
    }

    // 获取某个课程的所有学生成绩
    async getCourseStudentScores(offering_id: number, teacher_tno: number) {
        // 验证教师权限
        const offering = await this.offeringRepo.findOne({
            where: { 
                offering_id,
                teacher: { tno: teacher_tno }
            },
            relations: ['course', 'teacher', 'semester']
        });

        if (!offering) {
            throw new NotFoundException('课程不存在或无权限访问');
        }

        // 获取该课程的所有选课学生及成绩
        const students = await this.selectRepo.find({
            where: {
                courseOffering: { offering_id },
                status: 'selected'
            },
            relations: ['student'],
            order: { student: { sno: 'ASC' } }
        });

        return {
            courseInfo: {
                offering_id: offering.offering_id,
                courseName: offering.course.cname,
                teacherName: offering.teacher.tname,
                semester: offering.semester.name,
                capacity: offering.capacity,
                enrolled_count: offering.enrolled_count
            },
            students: students.map(student => ({
                select_id: student.select_id,
                sno: student.student.sno,
                sname: student.student.sname,
                score: student.score,
                selectTime: student.selectTime
            }))
        };
  }
}
